<template>
  <div :class="getWrapClass">
    <div class="h-tabs" ref="tabsRef">
      <Draggable
        group="form-draggable"
        class="h-tab-darg"
        tag="div"
        :component-data="{
          tag: 'div',
          type: 'transition-group',
          name: 'list',
        }"
        :disabled="!isDarg"
        ghostClass="moving"
        :animation="180"
        :list="dataSource"
        item-key="key"
        @update="changeDarg"
      >
        <!-- handle=".th-drag" -->
        <template #item="{ element: item, index }">
          <div
            :class="[
              'h-tab',
              {
                'h-tab-active': activeRef === item.value,
              },
            ]"
            @click="chagneActive(item, index)"
          >
            <slot name="tab" v-bind="{ ...item, idx: index }"> {{ item.label }}</slot>
          </div>
        </template>
      </Draggable>
      <div class="extra">
        <slot name="extra"></slot>
      </div>
      <div class="h-tabs-bar" :style="barStyle"></div>
    </div>
  </div>
</template>

<script lang="ts">
  import { defineComponent, ref, nextTick, computed, watch } from 'vue';
  import { useDesign } from '/@/hooks/web/useDesign';
  import { basicProps } from './props';
  import { isNullOrUnDef } from '/@/utils/is';
  import { TabType } from './typing';
  import Draggable from 'vuedraggable';

  export default defineComponent({
    name: 'Tabs',
    components: { Draggable },
    props: basicProps,
    emits: ['update:active', 'change'],
    setup(props, { emit }) {
      const { prefixCls } = useDesign('h-tabs');

      const activeRef = ref();

      const tabsRef = ref<HTMLElement>();

      const barStyle = ref({ left: '' });

      const actInfo = computed(() => {
        const item = props.dataSource.find((el) => el.value === activeRef.value);

        return item || props.dataSource[0];
      });

      watch(
        () => activeRef.value,
        (v) => {
          emit('update:active', v);
          setTimeout(() => getBarLeft(), 20);
        },
      );
      watch(
        () => props.active,
        (v) => {
          if (activeRef.value !== v) {
            activeRef.value = v;
          }
        },
      );
      watch(
        () => props.dataSource,
        (v) => {
          if (isNullOrUnDef(activeRef.value) && v.length) {
            activeRef.value = v[0].value;
          }
        },
        { deep: true, immediate: true },
      );

      const getWrapClass = computed(() => {
        return [prefixCls];
      });

      const getBarLeft = () => {
        nextTick(() => {
          const activeEl = tabsRef.value?.querySelector('.h-tab-active') as HTMLElement;
          if (activeEl) {
            const barOffset = actInfo.value.barOffset || 0;

            // console.dir(activeEl.offsetLeft);
            const { clientWidth, offsetLeft } = activeEl;
            const selfBar = 14;
            const left = barOffset + offsetLeft - selfBar + clientWidth / 2;
            barStyle.value.left = left + 'px';
          }
        });
      };

      const chagneActive = (item: TabType, idx) => {
        if (activeRef.value === item.value) return;
        emit('change', item, idx);
        activeRef.value = item.value;
      };

      const changeDarg = ({ newIndex }) => {
        const item = props.dataSource[newIndex];
        emit('change', item, newIndex);
        activeRef.value = item.value;
        getBarLeft();
      };

      const getTabsHeight = () => {
        if (tabsRef.value) {
          return tabsRef.value.offsetHeight + 1;
        } else {
          throw 'Element is null';
        }
      };
      return {
        getWrapClass,
        barStyle,
        tabsRef,
        activeRef,
        chagneActive,
        changeDarg,
        getTabsHeight,
      };
    },
  });
</script>
<style lang="less" scoped>
  @import './index.less';
</style>
